home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / Level 1 Extensions 20Jul94 / BufferedFileInput.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  11.2 KB  |  406 lines  |  [TEXT/KAHL]

  1. /* BufferedFileInput.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Audit.h"
  21. #include "Debug.h"
  22. #include "Definitions.h"
  23.  
  24. #include "BufferedFileInput.h"
  25. #include "Files.h"
  26. #include "Memory.h"
  27.  
  28.  
  29. #define BUFFERSIZE (4096) /* must be a power of two! */
  30. #define BUFFERMASK (BUFFERSIZE - 1)
  31.  
  32.  
  33. /* this structure is simple because we only handle sequential reading. */
  34. struct BufferedInputRec
  35.     {
  36.         FileType*                FileDescriptor;
  37.         long                        IndexIntoBuffer;
  38.         long                        IndexIntoFileOfStartOfBuffer;
  39.         long                        LengthOfFile;
  40.         MyBoolean                ErrorOcurredCantBeUsed;
  41.         char                        Buffer[BUFFERSIZE];
  42.     };
  43.  
  44.  
  45. static MyBoolean        FillBuffer(BufferedInputRec* BufferedThang)
  46.     {
  47.         long                            NumBytesToRead;
  48.         long                            ReadResult;
  49.  
  50.         CheckPtrExistence(BufferedThang);
  51.         ERROR(BufferedThang->ErrorOcurredCantBeUsed,PRERR(ForceAbort,
  52.             "FillBuffer:  error occurred and buffer can not be used"));
  53.         if (BufferedThang->IndexIntoFileOfStartOfBuffer + BUFFERSIZE
  54.             > BufferedThang->LengthOfFile)
  55.             {
  56.                 NumBytesToRead = BufferedThang->LengthOfFile
  57.                     - BufferedThang->IndexIntoFileOfStartOfBuffer;
  58.             }
  59.          else
  60.             {
  61.                 NumBytesToRead = BUFFERSIZE;
  62.             }
  63.         ERROR(GetFilePosition(BufferedThang->FileDescriptor)
  64.             != BufferedThang->IndexIntoFileOfStartOfBuffer,PRERR(ForceAbort,
  65.             "FillBuffer:  buffer index is out of sync with the file"));
  66.         if (0 != ReadFromFile(BufferedThang->FileDescriptor,&(BufferedThang->Buffer[0]),
  67.             NumBytesToRead))
  68.             {
  69.                 BufferedThang->ErrorOcurredCantBeUsed = True;
  70.                 return False;
  71.             }
  72.         return True;
  73.     }
  74.  
  75.  
  76. /* create a new buffered input object around a file.  the file is not allowed */
  77. /* to be tampered with after it has been registered with this since I am too */
  78. /* lazy to implement proper buffering in the Level 0 library like I should. */
  79. BufferedInputRec*        NewBufferedInput(struct FileType* TheFileDescriptor)
  80.     {
  81.         BufferedInputRec*    BufferedThang;
  82.         long                            FilePosition;
  83.  
  84.         CheckPtrExistence(TheFileDescriptor);
  85.  
  86.         BufferedThang = (BufferedInputRec*)AllocPtrCanFail(sizeof(BufferedInputRec),
  87.             "BufferedInputRec");
  88.         if (BufferedThang == NIL)
  89.             {
  90.              FailurePoint1:
  91.                 return NIL;
  92.             }
  93.  
  94.         BufferedThang->FileDescriptor = TheFileDescriptor;
  95.  
  96.         BufferedThang->LengthOfFile = GetFileLength(TheFileDescriptor);
  97.  
  98.         FilePosition = GetFilePosition(TheFileDescriptor);
  99.         BufferedThang->IndexIntoBuffer = FilePosition & BUFFERMASK;
  100.         BufferedThang->IndexIntoFileOfStartOfBuffer = FilePosition & (~BUFFERMASK);
  101.  
  102.         BufferedThang->ErrorOcurredCantBeUsed = False;
  103.  
  104.         if (!SetFilePosition(TheFileDescriptor,BufferedThang->IndexIntoFileOfStartOfBuffer))
  105.             {
  106.              FailurePoint2:
  107.                 ReleasePtr((char*)BufferedThang);
  108.                 goto FailurePoint1;
  109.             }
  110.         if (!FillBuffer(BufferedThang))
  111.             {
  112.              FailurePoint3:
  113.                 goto FailurePoint2;
  114.             }
  115.  
  116.         return BufferedThang;
  117.     }
  118.  
  119.  
  120. /* clean up a buffered input object from around a file.  the file may be */
  121. /* used normally after this has been called. */
  122. void                                EndBufferedInput(BufferedInputRec* BufferedThang)
  123.     {
  124.         CheckPtrExistence(BufferedThang);
  125.         if (!BufferedThang->ErrorOcurredCantBeUsed)
  126.             {
  127.                 (void)SetFilePosition(BufferedThang->FileDescriptor,
  128.                     BufferedThang->IndexIntoBuffer + BufferedThang->IndexIntoFileOfStartOfBuffer);
  129.             }
  130.         ReleasePtr((char*)BufferedThang);
  131.     }
  132.  
  133.  
  134. /* read a raw block of data from the file.  returns True if all went well or */
  135. /* False if some data could not be written to the file. */
  136. MyBoolean                        ReadBufferedInput(BufferedInputRec* BufferedThang,
  137.                                             long RequestedBytes, char* PlaceToPut)
  138.     {
  139.         CheckPtrExistence(BufferedThang);
  140.         ERROR(BufferedThang->ErrorOcurredCantBeUsed,PRERR(ForceAbort,
  141.             "ReadBufferedInput:  error ocurred, so buffer is no longer valid"));
  142.         ERROR(RequestedBytes < 0,PRERR(ForceAbort,
  143.             "ReadBufferedInput:  bad requested bytes"));
  144.  
  145.         /* do the read loop */
  146.         while (RequestedBytes > 0)
  147.             {
  148.                 if (BufferedThang->IndexIntoBuffer + BufferedThang->IndexIntoFileOfStartOfBuffer
  149.                     >= BufferedThang->LengthOfFile)
  150.                     {
  151.                         /* ran out of bytes, so we'll just tell them */
  152.                         BufferedThang->ErrorOcurredCantBeUsed = True;
  153.                         return False;
  154.                     }
  155.                 *PlaceToPut = BufferedThang->Buffer[BufferedThang->IndexIntoBuffer];
  156.                 BufferedThang->IndexIntoBuffer += 1;
  157.                 PlaceToPut += 1;
  158.                 RequestedBytes -= 1;
  159.                 if (BufferedThang->IndexIntoBuffer == BUFFERSIZE)
  160.                     {
  161.                         /* if we ran off the end of the file, then load increment internal indices */
  162.                         BufferedThang->IndexIntoBuffer = 0;
  163.                         BufferedThang->IndexIntoFileOfStartOfBuffer += BUFFERSIZE;
  164.                         /* load the next block from the disk */
  165.                         if (!FillBuffer(BufferedThang))
  166.                             {
  167.                                 BufferedThang->ErrorOcurredCantBeUsed = True;
  168.                                 return False;
  169.                             }
  170.                     }
  171.             }
  172.  
  173.         return True;
  174.     }
  175.  
  176.  
  177. /* read in a signed (2's complement) character.  returns True if successful. */
  178. MyBoolean                        ReadBufferedSignedChar(BufferedInputRec* BufferedThang,
  179.                                             signed char* SignedCharOut)
  180.     {
  181.         char                            Buff[1];
  182.  
  183.         CheckPtrExistence(BufferedThang);
  184.         if (!ReadBufferedInput(BufferedThang,1,Buff))
  185.             {
  186.                 return False;
  187.             }
  188.         if ((Buff[0] & 0x80) != 0)
  189.             {
  190.                 *SignedCharOut = ~0x7f | (Buff[0] & 0x7f);
  191.             }
  192.          else
  193.             {
  194.                 *SignedCharOut = Buff[0] & 0x7f;
  195.             }
  196.         return True;
  197.     }
  198.  
  199.  
  200. /* read in an unsigned character.  returns True if successful. */
  201. MyBoolean                        ReadBufferedUnsignedChar(BufferedInputRec* BufferedThang,
  202.                                             unsigned char* UnsignedCharOut)
  203.     {
  204.         char                            Buff[1];
  205.  
  206.         CheckPtrExistence(BufferedThang);
  207.         if (!ReadBufferedInput(BufferedThang,1,Buff))
  208.             {
  209.                 return False;
  210.             }
  211.         *UnsignedCharOut = Buff[0] & 0xff;
  212.         return True;
  213.     }
  214.  
  215.  
  216. /* read in a signed (2's complement) 16-bit short little endian.  returns True if sucessful. */
  217. MyBoolean                        ReadBufferedSignedShortLittleEndian(BufferedInputRec* BufferedThang,
  218.                                             signed short* SignedShortOut)
  219.     {
  220.         char                            Buff[2];
  221.  
  222.         CheckPtrExistence(BufferedThang);
  223.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  224.             {
  225.                 return False;
  226.             }
  227.         if ((Buff[1] & 0x80) != 0)
  228.             {
  229.                 *SignedShortOut
  230.                     = (0xff & Buff[0])
  231.                     | ((~0x7f | ((short)Buff[1] & 0x7f)) << 8);
  232.             }
  233.          else
  234.             {
  235.                 *SignedShortOut
  236.                     = (0xff & Buff[0])
  237.                     | (((short)Buff[1] & 0x7f) << 8);
  238.             }
  239.         return True;
  240.     }
  241.  
  242.  
  243. /* read in a signed (2's complement) 16-bit short big endian.  returns True if sucessful. */
  244. MyBoolean                        ReadBufferedSignedShortBigEndian(BufferedInputRec* BufferedThang,
  245.                                             signed short* SignedShortOut)
  246.     {
  247.         char                            Buff[2];
  248.  
  249.         CheckPtrExistence(BufferedThang);
  250.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  251.             {
  252.                 return False;
  253.             }
  254.         if ((Buff[0] & 0x80) != 0)
  255.             {
  256.                 *SignedShortOut
  257.                     = (0xff & Buff[1])
  258.                     | ((~0x7f | ((short)Buff[0] & 0x7f)) << 8);
  259.             }
  260.          else
  261.             {
  262.                 *SignedShortOut
  263.                     = (0xff & Buff[1])
  264.                     | (((short)Buff[0] & 0x7f) << 8);
  265.             }
  266.         return True;
  267.     }
  268.  
  269.  
  270. /* read in an unsigned 16-bit short little endian.  returns True if successful. */
  271. MyBoolean                        ReadBufferedUnsignedShortLittleEndian(BufferedInputRec* BufferedThang,
  272.                                             unsigned short* UnsignedShortOut)
  273.     {
  274.         char                            Buff[2];
  275.  
  276.         CheckPtrExistence(BufferedThang);
  277.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  278.             {
  279.                 return False;
  280.             }
  281.         *UnsignedShortOut
  282.             = (0xff & Buff[0])
  283.             | (((short)Buff[1] & 0xff) << 8);
  284.         return True;
  285.     }
  286.  
  287.  
  288. /* read in an unsigned 16-bit short big endian.  returns True if successful. */
  289. MyBoolean                        ReadBufferedUnsignedShortBigEndian(BufferedInputRec* BufferedThang,
  290.                                             unsigned short* UnsignedShortOut)
  291.     {
  292.         char                            Buff[2];
  293.  
  294.         CheckPtrExistence(BufferedThang);
  295.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  296.             {
  297.                 return False;
  298.             }
  299.         *UnsignedShortOut
  300.             = (0xff & Buff[1])
  301.             | (((short)Buff[0] & 0xff) << 8);
  302.         return True;
  303.     }
  304.  
  305.  
  306. /* read in a signed (2's complement) 32-bit long little endian.  returns True if successful. */
  307. MyBoolean                        ReadBufferedSignedLongLittleEndian(BufferedInputRec* BufferedThang,
  308.                                             signed long* SignedLongOut)
  309.     {
  310.         char                            Buff[4];
  311.  
  312.         CheckPtrExistence(BufferedThang);
  313.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  314.             {
  315.                 return False;
  316.             }
  317.         if ((Buff[3] & 0x80) != 0)
  318.             {
  319.                 *SignedLongOut
  320.                     = (0xff & Buff[0])
  321.                     | ((0xff & (long)Buff[1]) << 8)
  322.                     | ((0xff & (long)Buff[2]) << 16)
  323.                     | ((~0x7f | ((long)Buff[3] & 0x7f)) << 24);
  324.             }
  325.          else
  326.             {
  327.                 *SignedLongOut
  328.                     = (0xff & Buff[0])
  329.                     | ((0xff & (long)Buff[1]) << 8)
  330.                     | ((0xff & (long)Buff[2]) << 16)
  331.                     | (((long)Buff[3] & 0x7f) << 24);
  332.             }
  333.         return True;
  334.     }
  335.  
  336.  
  337. /* read in a signed (2's complement) 32-bit long big endian.  returns True if successful. */
  338. MyBoolean                        ReadBufferedSignedLongBigEndian(BufferedInputRec* BufferedThang,
  339.                                             signed long* SignedLongOut)
  340.     {
  341.         char                            Buff[4];
  342.  
  343.         CheckPtrExistence(BufferedThang);
  344.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  345.             {
  346.                 return False;
  347.             }
  348.         if ((Buff[0] & 0x80) != 0)
  349.             {
  350.                 *SignedLongOut
  351.                     = (0xff & Buff[3])
  352.                     | ((0xff & (long)Buff[2]) << 8)
  353.                     | ((0xff & (long)Buff[1]) << 16)
  354.                     | ((~0x7f | ((long)Buff[0] & 0x7f)) << 24);
  355.             }
  356.          else
  357.             {
  358.                 *SignedLongOut
  359.                     = (0xff & Buff[3])
  360.                     | ((0xff & (long)Buff[2]) << 8)
  361.                     | ((0xff & (long)Buff[1]) << 16)
  362.                     | (((long)Buff[0] & 0x7f) << 24);
  363.             }
  364.         return True;
  365.     }
  366.  
  367.  
  368. /* read in an unsigned 32-bit long little endian.  returns True if successful. */
  369. MyBoolean                        ReadBufferedUnsignedLongLittleEndian(BufferedInputRec* BufferedThang,
  370.                                             unsigned long* UnsignedLongOut)
  371.     {
  372.         char                            Buff[4];
  373.  
  374.         CheckPtrExistence(BufferedThang);
  375.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  376.             {
  377.                 return False;
  378.             }
  379.         *UnsignedLongOut
  380.             = (0xff & Buff[0])
  381.             | ((0xff & (long)Buff[1]) << 8)
  382.             | ((0xff & (long)Buff[2]) << 16)
  383.             | (((long)Buff[3] & 0xff) << 24);
  384.         return True;
  385.     }
  386.  
  387.  
  388. /* read in an unsigned 32-bit long big endian.  returns True if successful. */
  389. MyBoolean                        ReadBufferedUnsignedLongBigEndian(BufferedInputRec* BufferedThang,
  390.                                             unsigned long* UnsignedLongOut)
  391.     {
  392.         char                            Buff[4];
  393.  
  394.         CheckPtrExistence(BufferedThang);
  395.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  396.             {
  397.                 return False;
  398.             }
  399.         *UnsignedLongOut
  400.             = (0xff & Buff[3])
  401.             | ((0xff & (long)Buff[2]) << 8)
  402.             | ((0xff & (long)Buff[1]) << 16)
  403.             | (((long)Buff[0] & 0xff) << 24);
  404.         return True;
  405.     }
  406.